package cn.kuporo.seckill.activity.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.kuporo.seckill.activity.application.cache.SeckillActivityCacheService;
import cn.kuporo.seckill.activity.application.cache.SeckillActivityListCacheService;
import cn.kuporo.seckill.activity.domain.model.vo.ActivitySaveReqVO;
import cn.kuporo.seckill.activity.application.service.SeckillActivityService;
import cn.kuporo.seckill.activity.domain.model.SeckillActivity;
import cn.kuporo.seckill.activity.domain.service.SeckillActivityDomainService;
import cn.kuporo.seckill.common.cache.model.SeckillBusinessCache;
import cn.kuporo.seckill.common.exception.ErrorCode;
import cn.kuporo.seckill.common.exception.SeckillException;
import cn.kuporo.seckill.common.model.dto.SeckillActivityDTO;
import cn.kuporo.seckill.common.model.enums.SeckillActivityStatus;
import cn.kuporo.seckill.common.model.response.Response;
import cn.kuporo.seckill.common.model.vo.FindActivityBySARspVO;
import cn.kuporo.seckill.common.utils.SnowFlakeFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: kuporo
 * @since: 2025/7/7
 * @description:
 */
@Service
@RequiredArgsConstructor
public class SeckillActivityServiceImpl implements SeckillActivityService {
    private final SeckillActivityDomainService seckillActivityDomainService;;
    private final SeckillActivityListCacheService seckillActivityListCacheService;
    private final SeckillActivityCacheService seckillActivityCacheService;

    @Override
    @Transactional
    public Response<?> saveSeckillActivity(ActivitySaveReqVO activitySaveReqVO) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = activitySaveReqVO.getStartTime();
        LocalDateTime endTime = activitySaveReqVO.getEndTime();
        if (startTime.isBefore(now)){
            throw new SeckillException(ErrorCode.PARAMS_INVALID.getErrorCode(), "活动开始时间不能小于当前时间");
        }
        if (endTime.isBefore(startTime)){
            throw new SeckillException(ErrorCode.PARAMS_INVALID.getErrorCode(), "活动结束时间不能小于活动开始时间");
        }
        SeckillActivity seckillActivity = new SeckillActivity();
        BeanUtils.copyProperties(activitySaveReqVO, seckillActivity);
        seckillActivity.setId(SnowFlakeFactory.getSnowFlakeFromCache().nextId());
        seckillActivity.setStatus(SeckillActivityStatus.PUBLISHED.getCode());
        seckillActivityDomainService.saveSeckillActivity(seckillActivity);
        return Response.success();
    }

    @Override
    public List<SeckillActivity> getSeckillActivityList(Integer status) {
        return seckillActivityDomainService.getSeckillActivityList(status);
    }

    @Override
    public List<SeckillActivity> getSeckillActivityListBetweenStartTimeAndEndTime(LocalDateTime currentTime, Integer status) {
        return seckillActivityDomainService.getSeckillActivityListBetweenStartTimeAndEndTime(currentTime, status);
    }

    @Override
    public SeckillActivity getSeckillActivityById(Long id) {
        return seckillActivityDomainService.getSeckillActivityById(id);
    }

    /**
     * 修改活动状态
     * @param id 活动id
     * @param status 活动状态
     */
    @Override
    public Response<?> updateStatus(Long id, Integer status) {
        seckillActivityDomainService.updateStatus(id, status);
        return Response.success();
    }

    @Override
    public List<FindActivityBySARspVO> getSeckillActivityList(Integer status, Long version) {
        SeckillBusinessCache<List<SeckillActivity>> seckillActivitiyListCache = seckillActivityListCacheService.getCachedActivities(status, version);
        if (!seckillActivitiyListCache.isExist()){
            throw new SeckillException(ErrorCode.ACTIVITY_NOT_EXISTS);
        }
        // 稍后再试，前端需要对这个状态做特殊处理，即不去刷新数据，静默稍后再试
        if (seckillActivitiyListCache.isRetryLater()){
            throw new SeckillException(ErrorCode.RETRY_LATER);
        }
        return seckillActivitiyListCache.getData().stream().map(seckillActivity -> {
            FindActivityBySARspVO findActivityBySARspVO = BeanUtil.toBean(seckillActivity, FindActivityBySARspVO.class);
            findActivityBySARspVO.setVersion(seckillActivitiyListCache.getVersion());
            return findActivityBySARspVO;
        }).collect(Collectors.toList());
    }

    /**
     * 获取活动信息(带缓存)
     * @param id 商品id
     * @param version 版本号
     * @return
     */
    @Override
    public SeckillActivityDTO getSeckillActivityById(Long id, Long version) {
        if (id == null){
            throw new SeckillException(ErrorCode.PARAMS_INVALID);
        }
        SeckillBusinessCache<SeckillActivity> seckillActivityCache = seckillActivityCacheService.getCachedSeckillActivity(id, version);
        //缓存中的活动数据不存在
        if (!seckillActivityCache.isExist()){
            throw new SeckillException(ErrorCode.ACTIVITY_NOT_EXISTS);
        }
        //稍后再试，前端需要对这个状态做特殊处理，即不去刷新数据，静默稍后再试
        if (seckillActivityCache.isRetryLater()){
            throw new SeckillException(ErrorCode.RETRY_LATER);
        }
        SeckillActivityDTO seckillActivityDTO = BeanUtil.toBean(seckillActivityCache.getData(), SeckillActivityDTO.class);
        seckillActivityDTO.setVersion(seckillActivityCache.getVersion());
        return seckillActivityDTO;
    }

}
